package cn.growthgate.fgo.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;

import cn.growthgate.fgo.common.Constants;
import cn.growthgate.fgo.common.base.BaseServiceImpl;
import cn.growthgate.fgo.entity.Menu;
import cn.growthgate.fgo.entity.enums.MenuType;
import cn.growthgate.fgo.entity.enums.Role;
import cn.growthgate.fgo.entity.vo.MenuVo;
import cn.growthgate.fgo.mapper.MenuMapper;
import cn.growthgate.fgo.service.IMenuService;
import cn.growthgate.fgo.util.ArrayUtils;
import cn.growthgate.fgo.util.AuthenticationUtils;
import cn.growthgate.fgo.util.CacheUtils;
import cn.growthgate.fgo.util.CollectionUtils;
import cn.growthgate.fgo.util.StringUtils;

/**
 * <p>
 * 菜单 服务实现类
 * </p>
 *
 * @author GrowthGate
 * @since 2019-04-27
 */
@Service
public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, Menu> implements IMenuService {

	public List<Menu> getRootMenus() {
		return baseMapper.selectList(newWrapper().eq("type", MenuType.DROPDOWN).orderBy("sort"));
	}

	@Override
	public MenuVo transformVo(Menu menu) {
		MenuVo vo = new MenuVo();
		vo.setId(menu.getId());
		if (menu.getParentId() != null) {
			Menu parent = baseMapper.selectById(menu.getParentId());
			vo.setParent(transformVo(parent));
		}
		vo.setType(menu.getType());
		vo.setName(menu.getName());
		vo.seteName(menu.geteName());
		vo.setUrl(menu.getUrl());
		vo.setSort(menu.getSort());
		vo.setRoles(getRoles(menu));
		return vo;
	}
	
	@Override
	public List<Role> getRoles(Menu menu) {
		Integer[] roleValues = StringUtils.splitToInteger(menu.getRoles(), ",");
		List<Role> roles = new ArrayList<>();
		for (Integer roleValue : roleValues) {
			for (Role role : Role.values()) {
				if (role.getValue().equals(roleValue)) {
					roles.add(role);
				}
			}
		}
		return roles;
	}
	
	public Map<Menu, List<Menu>> getUserMenus() {
		// 从缓存中获取
		Long userId = AuthenticationUtils.getLoginUserId();
		userId = userId != null ? userId : 0;
		Map<Menu, List<Menu>> result = CacheUtils.get(Constants.CACHE_USER_MENUS, userId);
		if (result != null) {
			return result;
		}
		// 获取数据库数据
		Wrapper<Menu> wrapper = new EntityWrapper<Menu>().orderBy("sort");
		List<Menu> menus = baseMapper.selectList(wrapper);
		List<Menu> roots = new ArrayList<>();
		Map<Long, List<Menu>> children = new HashMap<>(); 
		for (Menu menu : menus) {
			Role[] roles = CollectionUtils.toArray(getRoles(menu), Role.class);
			if (ArrayUtils.isEmpty(roles) || AuthenticationUtils.hasAnyRoles(roles)) {
				// 用户拥有权限
				Long parentId = menu.getParentId();
				if (parentId == null) {
					// 根菜单
					roots.add(menu);
				} else {
					// 子菜单
					List<Menu> child = children.get(parentId);
					if (child == null) {
						child = new ArrayList<>();
						children.put(parentId, child);
					}
					child.add(menu);
				}
			}
		}
		result = roots.stream().collect(Collectors.toMap(menu -> menu,
				menu -> children.getOrDefault(menu.getId(), Collections.emptyList()), (a, b) -> a, LinkedHashMap::new));
		// 存入缓存
		CacheUtils.put(Constants.CACHE_USER_MENUS, userId, result);
		return result;
	}
	
}
